package com.dh.project.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.dh.project.model.*;
import com.dh.project.model.push.PageType;
import com.dh.project.other.ModelRes;
import com.dh.project.service.CouponService;
import com.dh.project.service.CustomerCouponService;
import com.dh.project.service.OrderInfoService;
import com.dh.project.utils.*;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * Created by admin on 2017/2/27.
 */
@Controller
public class PayController {

    @Autowired
    public PayController(CustomerCouponService customerCouponService, OrderInfoService orderInfoService, CouponService couponService) {
        this.customerCouponService = customerCouponService;
        this.orderInfoService = orderInfoService;
        this.couponService = couponService;
    }

    /**
     * 获取微信支付订单号
     *
     * @param customer_id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getWeiXinPrepayId", produces = "text/html;charset=utf-8")
    public Object getWeiXinPrepayId(String price, int customer_id, String shop) throws Exception {
        final String nonceStr = (System.currentTimeMillis() / 1000) + "";
        GetPrepayId get = (GetPrepayId) PayUtil.getObjectFromXML(PayUtil.getPrepayId(price, customer_id, nonceStr, shop), GetPrepayId.class);
        Map<String, String> map = new HashMap<>();
        map.put("appid", PayUtil.ConstWecheat.APP_ID);
        map.put("noncestr", nonceStr);
        map.put("package", PayUtil.ConstWecheat.PACKAGE_VALUE);
        map.put("prepayid", get.getPrepay_id());
        map.put("partnerid", PayUtil.ConstWecheat.MCH_ID);
        map.put("timestamp", nonceStr);
        String sign = PayUtil.getSign(map);
        get.setSign(sign);
        get.setTimestamp(nonceStr);
        return get;
    }

    public int checkCoupon(OrderInfo orderInfo, int coupon_id,double price) {

        if (orderInfo == null) {
//            return new ModelRes(ModelRes.Status.ERROR, "未查询到订单信息!");
            return 1;
        }
        CustomerCoupon customerCoupon = null;
        if (coupon_id != 0) {
            customerCoupon = customerCouponService.selectById(coupon_id);

            if (customerCoupon.getIs_use() == 2) {
//                return new ModelRes(ModelRes.Status.ERROR, "该优惠券已过期！");
                return 2;
            }
            if (customerCoupon.getIs_out() == 2) {
//                return new ModelRes(ModelRes.Status.ERROR, "该优惠券已使用！");
                return 3;
            }
        }
        if (orderInfo.getOrder_status() != 5) {
//            return new ModelRes(ModelRes.Status.ERROR, "该订单状态下不能支付！");
            return 4;
        }
        if (coupon_id != 0) {
            Coupon coupon = couponService.selectById(customerCoupon.getCoupon_id());
            if (coupon == null) {
//                return new ModelRes(ModelRes.Status.ERROR, "未查询到优惠券信息!");
                return 5;
            }
            orderInfo.setCoupon_price(coupon.getPrice().doubleValue());
            orderInfo.setCustomer_coupon_id(coupon_id);
            double orderPrice = StringUtil.doubleSub(orderInfo.getOrder_price(), orderInfo.getCoupon_price());
            orderPrice = orderPrice < 0 ? 0 : orderPrice;
            orderInfo.setOrder_price(price);
            if(orderPrice==price){
                orderInfo.setOrder_price(price);
            }else{
                return 7;
            }


            orderInfoService.updateById(orderInfo);
//            customerCoupon.setIs_out(2);
//            if (!customerCouponService.updateById(customerCoupon)) {
////                return new ModelRes(ModelRes.Status.ERROR, "优惠券使用错误!");
//                return 6;
//            }
        }
        return 0;
    }


    /**
     * 对订单信息进行签名
     * 支付宝、微信共用
     * json {}
     */

    @RequestMapping(value = "signedOrderInfo", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public Object payOrderSign(int order_id, int coupon_id, Double price, Integer type) {


        OrderInfo orderInfo = orderInfoService.selectById(order_id);

        switch (checkCoupon(orderInfo, coupon_id,price)) {
            default:
                return new ModelRes(ModelRes.Status.ERROR, "其他错误！");
            case 0:
                //优惠券操作成功
                break;
            case 1:
                return new ModelRes(ModelRes.Status.ERROR, "未查询到订单信息！");
            case 2:
                return new ModelRes(ModelRes.Status.ERROR, "该优惠券已过期！");
            case 3:
                return new ModelRes(ModelRes.Status.ERROR, "该优惠券已使用！");
            case 4:
                return new ModelRes(ModelRes.Status.ERROR, "该订单状态下不能支付！");
            case 5:
                return new ModelRes(ModelRes.Status.ERROR, "未查询到优惠券信息！");
            case 6:
                return new ModelRes(ModelRes.Status.ERROR, "优惠券使用错误！");
            case 7:
                return new ModelRes(ModelRes.Status.ERROR, "提交价格错误！");

        }

        switch (type) {
            default:
                return new ModelRes(ModelRes.Status.ERROR, "其他支付方式尚未开通");
            case 1://支付宝充值
                //实例化客户端
                AlipayClient alipayClient = new DefaultAlipayClient(PayUtil.ConstAli.SERVER_URL, PayUtil.ConstAli.APP_ID, PayUtil.ConstAli.PRIVATEKEY, "json", "UTF-8", PayUtil.ConstAli.PUBLICKEY, "RSA2");
                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
                //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setBody("" + order_id);
                model.setSubject(order_id + "");
                model.setOutTradeNo(System.currentTimeMillis() + order_id + "");
                model.setTimeoutExpress("30m");
                model.setTotalAmount(price + "");
                model.setProductCode(PayUtil.ConstAli.PRODUCT_CODE);
                aliRequest.setBizModel(model);
                aliRequest.setNotifyUrl(PayUtil.ConstAli.ALI_CALLBACK_URL);
                try {
                    //这里和普通的接口调用不同，使用的是sdkExecute
                    AlipayTradeAppPayResponse response = alipayClient.sdkExecute(aliRequest);
                    Map<String, String> map = new HashMap<>();
                    map.put("info", response.getBody());
                    System.out.println("返回给客户端的订单信息》》》》》》》》》》》》》》》》" + response.getBody());//就是orderString 可以直接给客户端请求，无需再做处理。
                    return new ModelRes(ModelRes.Status.SUCCESS, "获取签名订单信息成功", map);
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                    return new ModelRes(ModelRes.Status.ERROR, "获取签名订单信息失败", null);
                }

//                return new ModelRes(ModelRes.Status.ERROR, "支付宝尚未开通");
            case 2://微信充值
                final String nonceStr = (System.currentTimeMillis() / 1000) + "";
                String responseStr = null;
                Map<String, String> paramMap = new HashMap<>();


                paramMap.put("appid", PayUtil.ConstWecheat.APP_ID); //appid：每个公众号都有一个appid
                paramMap.put("mch_id", PayUtil.ConstWecheat.MCH_ID); //商户号：开通微信支付后分配
                paramMap.put("nonce_str", nonceStr);//随机数
                paramMap.put("body", "" + order_id); //商品描述
                paramMap.put("attach", order_id + ""); //附加数据
                paramMap.put("out_trade_no", System.currentTimeMillis() + order_id + "");//商户订单号
                paramMap.put("total_fee", StringUtil.DoubleToAmountString(price * 100, 0)); //金额必须为整数  单位为分
                paramMap.put("spbill_create_ip", "192.168.1.1"); //本机的Ip
                paramMap.put("notify_url", PayUtil.ConstWecheat.wxNotifyUrl); //支付成功后，回调地址
                paramMap.put("trade_type", "APP"); //交易类型

                System.out.println("paramMap>>>>>>>>>>>>>>" + paramMap);

                //调用签名函数生成签名
                String result = sign(paramMap);


                paramMap.put("sign", result);//根据微信签名规则，生成签名。随机参数可以在商户后台管理系统中进行设置。
                StringBuffer stringBuffer = new StringBuffer("<xml>");//把参数转换成XML数据格式
                PayUtil.mapToXML(paramMap, stringBuffer);
                stringBuffer.append("</xml>");
                System.out.println("微信提交xml: \n" + stringBuffer.toString());

                okhttp3.RequestBody requestBody = okhttp3.RequestBody.create(MediaType.parse("utf-8"), stringBuffer.toString());
                Request request = new Request.Builder().addHeader("Content-Type", "text/xml").url(PayUtil.ConstWecheat.prepayId).post(requestBody).build();


                OkHttpClient okHttpClient = new OkHttpClient();
                try {
                    Response response = okHttpClient.newCall(request).execute();
                    responseStr = response.body().string();

                    WeiXinSign weiXinSign = (WeiXinSign) JsonUtil.getObjectFromXML(responseStr, WeiXinSign.class);


                    Map<String, String> signMap = new HashMap<>();
                    signMap.put("appid", weiXinSign.getAppid());
                    signMap.put("partnerid", PayUtil.ConstWecheat.MCH_ID);
                    signMap.put("prepayid", weiXinSign.getPrepay_id());
                    signMap.put("package", PayUtil.ConstWecheat.PACKAGE_VALUE);
                    signMap.put("noncestr", weiXinSign.getNonce_str());
                    signMap.put("timestamp", nonceStr);
                    String sign = sign(signMap);

                    weiXinSign.setPackage_value(PayUtil.ConstWecheat.PACKAGE_VALUE);
                    weiXinSign.setTimestamp(nonceStr);
                    weiXinSign.setSign(sign);
                    System.out.println("weiXinSign>>>>>>>>>>>>>>>" + weiXinSign.toString());
                    if (weiXinSign.getResult_code().equals("SUCCESS") && weiXinSign.getReturn_code().equals("SUCCESS")) {
                        return new ModelRes(ModelRes.Status.SUCCESS, "获取签名订单信息成功", weiXinSign);
                    } else {
                        return new ModelRes(ModelRes.Status.ERROR, "获取签名订单信息失败", weiXinSign);
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("支付失败信息>>>>>>>>>>>>>>>" + responseStr);
                    return new ModelRes(ModelRes.Status.ERROR, "获取签名订单信息失败", null);
                }
        }


    }

    /**
     * 支付宝回调(新版本)
     * notify_time   通知时间
     * charset       编码格式
     * trade_no      支付宝交易凭证号
     * trade_status  交易状态
     * total_amount  交易金额
     * subject       客户手机号
     */
    @RequestMapping(value = "AliPayResult", produces = "text/html;charset=utf-8")
    public String AliPayResult(HttpServletRequest request) throws Exception {
        Map requestParams = request.getParameterMap();

        System.out.println("Map:" + JsonUtil.toJson(requestParams));

        ALIPayResult aliPayResult = JsonUtil.json2Bean(JsonUtil.toJson(requestParams), ALIPayResult.class);

        System.out.println("aliPayResult:  " + aliPayResult.toString());

        System.out.println("交易状态：" + request.getParameter("trade_status"));
        System.out.println("交易金额：" + request.getParameter("total_amount"));
        System.out.println("流水号：" + request.getParameter("trade_no"));
        System.out.println("order_id：" + request.getParameter("body"));

        if (request.getParameter("trade_status") != null && request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
//            prepaidMapper.UpdatePrepaidByNo(request.getParameter("out_trade_no"));
//            Prepaid prepaid = prepaidMapper.SelectPrepaidByNo(request.getParameter("out_trade_no"));
//            System.out.println("支付单信息》》》》》》》》》》》》》》》》" + prepaid);
//            rechargenoResult(prepaid.getCustomerId(), prepaid.getTotalAmount(), 1, 2, request.getParameter("trade_no"), "您在APP端使用支付宝充值");
            return resultSuccess(request.getParameter("body"));
        }
        return "error";
    }

    /**
     * 微信支付回调接口(新版本)
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "WeiXinPayResultNew", produces = "text/html;charset=utf-8")
    public String WeiXinPayResultNew(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String inputLine;
        StringBuffer notifyXml = new StringBuffer();
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notifyXml.append(inputLine);
                System.out.println("");
            }
            request.getReader().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("notifyXml:" + notifyXml.toString());
        GetWXResult get = (GetWXResult) JsonUtil.getObjectFromXML(notifyXml.toString(), GetWXResult.class);
        System.out.println("notifyObj:" + get.toString());

        if (get.getResult_code().equals("SUCCESS")) {
            return resultSuccess(get.getAttach());
        }

        return "error";


    }

    /**
     * @param order_id
     * @return
     */
    private String resultSuccess(String order_id) {
        OrderInfo orderInfo = orderInfoService.selectById(order_id);
        CustomerCoupon customerCoupon = customerCouponService.selectById(orderInfo.getCustomer_coupon_id());
        if(null!=customerCoupon){
            customerCoupon.setIs_out(2);
            customerCouponService.updateById(customerCoupon);
        }

        //20180102-状态从6(待收款)改成7(已完成)-lex
        LogUtil.i("20180102-状态从6(待收款)改成7(已完成)-lex");
        orderInfo.setOrder_status(7);
        orderInfo.setModifytime(String.valueOf(System.currentTimeMillis()));
        if (!orderInfoService.updateById(orderInfo)) {
            return "error";
        }

        List<String> aliasList = new ArrayList<>();
        aliasList.add(orderInfo.getCustomer_id().toString());


        PushUtil.pushOne(aliasList, "在线支付成功，感谢您使用本公司的产品", JSON.toJSON(new PageType(1, orderInfo.getOrder_id().toString())));
        aliasList.clear();
        aliasList.add(orderInfo.getEmployee_id().toString());
        WorkerPushUtil.pushOne(aliasList, "订单" + orderInfo.getOrder_id() + "，用户在线付款成功，请尽快确认！", JSON.toJSON(new PageType(1, orderInfo.getOrder_id().toString())));

        return "PayResult";
    }

    public String sign(Map<String, String> paramMap) {
        //生成签名
        ArrayList<String> list = new ArrayList<>();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            if (entry.getValue() != "") {
                list.add(entry.getKey() + "=" + entry.getValue() + "&");
            }
        }
        int size = list.size();
        String[] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder resultStringBuilder = new StringBuilder();
        for (int i = 0; i < size; i++) {
            resultStringBuilder.append(arrayToSort[i]);
        }
        System.out.println("resultStringBuilder》》》》》》》》》" + resultStringBuilder);
        String result = resultStringBuilder.toString();
        result += "key=" + PayUtil.ConstWecheat.API_KEY;
        System.out.println("result>>>>>>>>>>>>>>>" + result);
        result = MD5.MD5Encode(result, "UTF-8").toUpperCase();
        System.out.println("MD5result>>>>>>>>>>>>>>>" + result);
        return result;
    }


    private CustomerCouponService customerCouponService;
    private OrderInfoService orderInfoService;
    private CouponService couponService;


}
